#!/usr/bin/env python3

r"""
Provide useful ipmi functions.
"""

import json
import re
import tempfile

import bmc_ssh_utils as bsu
import gen_cmd as gc
import gen_misc as gm
import gen_print as gp
import gen_robot_keyword as grk
import gen_robot_utils as gru
import ipmi_client as ic
import var_funcs as vf
from robot.libraries.BuiltIn import BuiltIn

gru.my_import_resource("ipmi_client.robot")


def get_sol_info():
    r"""
    Get all SOL info and return it as a dictionary.

    Example use:

    Robot code:
    ${sol_info}=  get_sol_info
    Rpvars  sol_info

    Output:
    sol_info:
      sol_info[Info]:                                SOL parameter 'Payload Channel (7)'
                                                     not supported - defaulting to 0x0e
      sol_info[Character Send Threshold]:            1
      sol_info[Force Authentication]:                true
      sol_info[Privilege Level]:                     USER
      sol_info[Set in progress]:                     set-complete
      sol_info[Retry Interval (ms)]:                 100
      sol_info[Non-Volatile Bit Rate (kbps)]:        IPMI-Over-Serial-Setting
      sol_info[Character Accumulate Level (ms)]:     100
      sol_info[Enabled]:                             true
      sol_info[Volatile Bit Rate (kbps)]:            IPMI-Over-Serial-Setting
      sol_info[Payload Channel]:                     14 (0x0e)
      sol_info[Payload Port]:                        623
      sol_info[Force Encryption]:                    true
      sol_info[Retry Count]:                         7
    """

    status, ret_values = grk.run_key_u(
        "Run External IPMI Standard Command  sol info"
    )

    # Create temp file path.
    temp = tempfile.NamedTemporaryFile()
    temp_file_path = temp.name

    # Write sol info to temp file path.
    text_file = open(temp_file_path, "w")
    text_file.write(ret_values)
    text_file.close()

    # Use my_parm_file to interpret data.
    sol_info = gm.my_parm_file(temp_file_path)

    return sol_info


def set_sol_setting(setting_name, setting_value):
    r"""
    Set SOL setting with given value.

    # Description of argument(s):
    # setting_name                  SOL setting which needs to be set (e.g.
    #                               "retry-count").
    # setting_value                 Value which needs to be set (e.g. "7").
    """

    status, ret_values = grk.run_key_u(
        "Run External IPMI Standard Command  sol set "
        + setting_name
        + " "
        + setting_value
    )

    return status


def execute_ipmi_cmd(
    cmd_string, ipmi_cmd_type="inband", print_output=1, ignore_err=0, **options
):
    r"""
    Run the given command string as an IPMI command and return the stdout,
    stderr and the return code.

    Description of argument(s):
    cmd_string                      The command string to be run as an IPMI
                                    command.
    ipmi_cmd_type                   'inband' or 'external'.
    print_output                    If this is set, this function will print
                                    the stdout/stderr generated by
                                    the IPMI command.
    ignore_err                      Ignore error means that a failure
                                    encountered by running the command
                                    string will not be raised as a python
                                    exception.
    options                         These are passed directly to the
                                    create_ipmi_ext_command_string function.
                                    See that function's prolog for details.
    """

    if ipmi_cmd_type == "inband":
        IPMI_INBAND_CMD = BuiltIn().get_variable_value("${IPMI_INBAND_CMD}")
        cmd_buf = IPMI_INBAND_CMD + " " + cmd_string
        return bsu.os_execute_command(
            cmd_buf, print_out=print_output, ignore_err=ignore_err
        )

    if ipmi_cmd_type == "external":
        cmd_buf = ic.create_ipmi_ext_command_string(cmd_string, **options)
        rc, stdout, stderr = gc.shell_cmd(
            cmd_buf,
            print_output=print_output,
            ignore_err=ignore_err,
            return_stderr=1,
        )
        return stdout, stderr, rc


def get_lan_print_dict(channel_number="", ipmi_cmd_type="external"):
    r"""
    Get IPMI 'lan print' output and return it as a dictionary.

    Here is an example of the IPMI lan print output:

    Set in Progress         : Set Complete
    Auth Type Support       : MD5
    Auth Type Enable        : Callback : MD5
                            : User     : MD5
                            : Operator : MD5
                            : Admin    : MD5
                            : OEM      : MD5
    IP Address Source       : Static Address
    IP Address              : x.x.x.x
    Subnet Mask             : x.x.x.x
    MAC Address             : xx:xx:xx:xx:xx:xx
    Default Gateway IP      : x.x.x.x
    802.1q VLAN ID          : Disabled
    Cipher Suite Priv Max   : Not Available
    Bad Password Threshold  : Not Available

    Given that data, this function will return the following dictionary.

    lan_print_dict:
      [Set in Progress]:                              Set Complete
      [Auth Type Support]:                            MD5
      [Auth Type Enable]:
        [Callback]:                                   MD5
        [User]:                                       MD5
        [Operator]:                                   MD5
        [Admin]:                                      MD5
        [OEM]:                                        MD5
      [IP Address Source]:                            Static Address
      [IP Address]:                                   x.x.x.x
      [Subnet Mask]:                                  x.x.x.x
      [MAC Address]:                                  xx:xx:xx:xx:xx:xx
      [Default Gateway IP]:                           x.x.x.x
      [802.1q VLAN ID]:                               Disabled
      [Cipher Suite Priv Max]:                        Not Available
      [Bad Password Threshold]:                       Not Available

    Description of argument(s):
    ipmi_cmd_type                   The type of ipmi command to use (e.g.
                                    'inband', 'external').
    """

    channel_number = str(channel_number)
    # Notice in the example of data above that 'Auth Type Enable' needs some
    # special processing.  We essentially want to isolate its data and remove
    # the 'Auth Type Enable' string so that key_value_outbuf_to_dict can
    # process it as a sub-dictionary.
    cmd_buf = (
        "lan print "
        + channel_number
        + " | grep -E '^(Auth Type Enable)"
        + "?[ ]+: ' | sed -re 's/^(Auth Type Enable)?[ ]+: //g'"
    )
    stdout1, stderr, rc = execute_ipmi_cmd(
        cmd_buf, ipmi_cmd_type, print_output=0
    )

    # Now get the remainder of the data and exclude the lines with no field
    # names (i.e. the 'Auth Type Enable' sub-fields).
    cmd_buf = "lan print " + channel_number + " | grep -E -v '^[ ]+: '"
    stdout2, stderr, rc = execute_ipmi_cmd(
        cmd_buf, ipmi_cmd_type, print_output=0
    )

    # Make auth_type_enable_dict sub-dictionary...
    auth_type_enable_dict = vf.key_value_outbuf_to_dict(
        stdout1, to_lower=0, underscores=0
    )

    # Create the lan_print_dict...
    lan_print_dict = vf.key_value_outbuf_to_dict(
        stdout2, to_lower=0, underscores=0
    )
    # Re-assign 'Auth Type Enable' to contain the auth_type_enable_dict.
    lan_print_dict["Auth Type Enable"] = auth_type_enable_dict

    return lan_print_dict


def get_ipmi_power_reading(strip_watts=1):
    r"""
    Get IPMI power reading data and return it as a dictionary.

    The data is obtained by issuing the IPMI "power reading" command.  An
    example is shown below:

    Instantaneous power reading:                   234 Watts
    Minimum during sampling period:                234 Watts
    Maximum during sampling period:                234 Watts
    Average power reading over sample period:      234 Watts
    IPMI timestamp:                           Thu Jan  1 00:00:00 1970
    Sampling period:                          00000000 Seconds.
    Power reading state is:                   deactivated

    For the data shown above, the following dictionary will be returned.

    result:
      [instantaneous_power_reading]:              238 Watts
      [minimum_during_sampling_period]:           238 Watts
      [maximum_during_sampling_period]:           238 Watts
      [average_power_reading_over_sample_period]: 238 Watts
      [ipmi_timestamp]:                           Thu Jan  1 00:00:00 1970
      [sampling_period]:                          00000000 Seconds.
      [power_reading_state_is]:                   deactivated

    Description of argument(s):
    strip_watts                     Strip all dictionary values of the
                                    trailing " Watts" substring.
    """

    status, ret_values = grk.run_key_u(
        "Run IPMI Standard Command  dcmi power reading"
    )
    result = vf.key_value_outbuf_to_dict(ret_values)

    if strip_watts:
        result.update((k, re.sub(" Watts$", "", v)) for k, v in result.items())

    return result


def get_mc_info():
    r"""
    Get IPMI mc info data and return it as a dictionary.

    The data is obtained by issuing the IPMI "mc info" command.  An
    example is shown below:

    Device ID                 : 0
    Device Revision           : 0
    Firmware Revision         : 2.01
    IPMI Version              : 2.0
    Manufacturer ID           : 42817
    Manufacturer Name         : Unknown (0xA741)
    Product ID                : 16975 (0x424f)
    Product Name              : Unknown (0x424F)
    Device Available          : yes
    Provides Device SDRs      : yes
    Additional Device Support :
        Sensor Device
        SEL Device
        FRU Inventory Device
        Chassis Device
    Aux Firmware Rev Info     :
        0x00
        0x00
        0x00
        0x00

    For the data shown above, the following dictionary will be returned.
    mc_info:
      [device_id]:                       0
      [device_revision]:                 0
      [firmware_revision]:               2.01
      [ipmi_version]:                    2.0
      [manufacturer_id]:                 42817
      [manufacturer_name]:               Unknown (0xA741)
      [product_id]:                      16975 (0x424f)
      [product_name]:                    Unknown (0x424F)
      [device_available]:                yes
      [provides_device_sdrs]:            yes
      [additional_device_support]:
        [additional_device_support][0]:  Sensor Device
        [additional_device_support][1]:  SEL Device
        [additional_device_support][2]:  FRU Inventory Device
        [additional_device_support][3]:  Chassis Device
      [aux_firmware_rev_info]:
        [aux_firmware_rev_info][0]:      0x00
        [aux_firmware_rev_info][1]:      0x00
        [aux_firmware_rev_info][2]:      0x00
        [aux_firmware_rev_info][3]:      0x00
    """

    status, ret_values = grk.run_key_u("Run IPMI Standard Command  mc info")
    result = vf.key_value_outbuf_to_dict(ret_values, process_indent=1)

    return result


def get_sdr_info():
    r"""
    Get IPMI sdr info data and return it as a dictionary.

    The data is obtained by issuing the IPMI "sdr info" command.  An
    example is shown below:

    SDR Version                         : 0x51
    Record Count                        : 216
    Free Space                          : unspecified
    Most recent Addition                :
    Most recent Erase                   :
    SDR overflow                        : no
    SDR Repository Update Support       : unspecified
    Delete SDR supported                : no
    Partial Add SDR supported           : no
    Reserve SDR repository supported    : no
    SDR Repository Alloc info supported : no

    For the data shown above, the following dictionary will be returned.
    mc_info:

      [sdr_version]:                         0x51
      [record_Count]:                        216
      [free_space]:                          unspecified
      [most_recent_addition]:
      [most_recent_erase]:
      [sdr_overflow]:                        no
      [sdr_repository_update_support]:       unspecified
      [delete_sdr_supported]:                no
      [partial_add_sdr_supported]:           no
      [reserve_sdr_repository_supported]:    no
      [sdr_repository_alloc_info_supported]: no
    """

    status, ret_values = grk.run_key_u("Run IPMI Standard Command  sdr info")
    result = vf.key_value_outbuf_to_dict(ret_values, process_indent=1)

    return result


def fetch_oem_sdr_count(sdr_data):
    r"""
    Get IPMI SDR list and return the SDR OEM count.

    The data is obtained by issuing the IPMI "sdr elist -vvv" command.  An
    example is shown below:

    SDR record ID   : 0x00cb
    SDR record ID   : 0x00cc
    SDR record type : 0xc0
    SDR record next : 0xffff
    SDR record bytes: 11
    Getting 11 bytes from SDR at offset 5

    For the data shown above, the SDR record type with 0xc0 count will be returned.
    """

    data = sdr_data.split("\n")
    sdr_list = []
    for i, j in enumerate(data):
        a = j.split(":")
        if a[0].strip() == "SDR record type":
            sdr_list.append(a[1].strip())
    return sdr_list.count("0xc0")


def get_aux_version(version_id):
    r"""
    Get IPMI Aux version info data and return it.

    Description of argument(s):
    version_id                      The data is obtained by from BMC
                                    /etc/os-release
                                    (e.g. "xxx-v2.1-438-g0030304-r3-gfea8585").

    In the prior example, the 3rd field is "438" is the commit version and
    the 5th field is "r3" and value "3" is the release version.

    Aux version return from this function 4380003.
    """

    # Commit version.
    count = re.findall("-(\\d{1,4})-", version_id)

    # Release version.
    release = re.findall("-r(\\d{1,4})", version_id)
    if release:
        aux_version = count[0] + "{0:0>4}".format(release[0])
    else:
        aux_version = count[0] + "0000"

    return aux_version


def get_fru_info():
    r"""
    Get fru info and return it as a list of dictionaries.

    The data is obtained by issuing the IPMI "fru print -N 50" command.  An
    example is shown below:

    FRU Device Description : Builtin FRU Device (ID 0)
     Device not present (Unspecified error)

    FRU Device Description : cpu0 (ID 1)
     Board Mfg Date        : Sun Dec 31 18:00:00 1995
     Board Mfg             : <Manufacturer Name>
     Board Product         : PROCESSOR MODULE
     Board Serial          : YA1934315964
     Board Part Number     : 02CY209

    FRU Device Description : cpu1 (ID 2)
     Board Mfg Date        : Sun Dec 31 18:00:00 1995
     Board Mfg             : <Manufacturer Name>
     Board Product         : PROCESSOR MODULE
     Board Serial          : YA1934315965
     Board Part Number     : 02CY209

    For the data shown above, the following list of dictionaries will be
    returned.

    fru_obj:
      fru_obj[0]:
        [fru_device_description]:  Builtin FRU Device (ID 0)
        [state]:                   Device not present (Unspecified error)
      fru_obj[1]:
        [fru_device_description]:  cpu0 (ID 1)
        [board_mfg_date]:          Sun Dec 31 18:00:00 1995
        [board_mfg]:               <Manufacturer Name>
        [board_product]:           PROCESSOR MODULE
        [board_serial]:            YA1934315964
        [board_part_number]:       02CY209
      fru_obj[2]:
        [fru_device_description]:  cpu1 (ID 2)
        [board_mfg_date]:          Sun Dec 31 18:00:00 1995
        [board_mfg]:               <Manufacturer Name>
        [board_product]:           PROCESSOR MODULE
        [board_serial]:            YA1934315965
        [board_part_number]:       02CY209
    """

    status, ret_values = grk.run_key_u(
        "Run IPMI Standard Command  fru print -N 50"
    )

    # Manipulate the "Device not present" line to create a "state" key.
    ret_values = re.sub(
        "Device not present", "state : Device not present", ret_values
    )

    return [
        vf.key_value_outbuf_to_dict(x) for x in re.split("\n\n", ret_values)
    ]


def get_component_fru_info(component="cpu", fru_objs=None):
    r"""
    Get fru info for the given component and return it as a list of
    dictionaries.

    This function calls upon get_fru_info and then filters out the unwanted
    entries.  See get_fru_info's prolog for a layout of the data.

    Description of argument(s):
    component                       The component (e.g. "cpu", "dimm", etc.).
    fru_objs                        A fru_objs list such as the one returned
                                    by get_fru_info.  If this is None, then
                                    this function will call get_fru_info to
                                    obtain such a list.
                                    Supplying this argument may improve
                                    performance if this function is to be
                                    called multiple times.
    """

    if fru_objs is None:
        fru_objs = get_fru_info()
    return [
        x
        for x in fru_objs
        if re.match(component + "([0-9]+)? ", x["fru_device_description"])
    ]


def get_user_info(userid, channel_number=1):
    r"""
    Get user info using channel command and return it as a dictionary.

    Description of argument(s):
    userid          The userid (e.g. "1", "2", etc.).
    channel_number  The user's channel number (e.g. "1").

    Note: If userid is blank, this function will return a list of dictionaries.  Each list entry represents
    one userid record.

    The data is obtained by issuing the IPMI "channel getaccess" command.  An
    example is shown below for user id 1 and channel number 1.

    Maximum User IDs     : 15
    Enabled User IDs     : 1
    User ID              : 1
    User Name            : root
    Fixed Name           : No
    Access Available     : callback
    Link Authentication  : enabled
    IPMI Messaging       : enabled
    Privilege Level      : ADMINISTRATOR
    Enable Status        : enabled

    For the data shown above, the following dictionary will be returned.

    user_info:
      [maximum_userids]:     15
      [enabled_userids:      1
      [userid]               1
      [user_name]            root
      [fixed_name]           No
      [access_available]     callback
      [link_authentication]  enabled
      [ipmi_messaging]       enabled
      [privilege_level]      ADMINISTRATOR
      [enable_status]        enabled
    """

    status, ret_values = grk.run_key_u(
        "Run IPMI Standard Command  channel getaccess "
        + str(channel_number)
        + " "
        + str(userid)
    )

    if userid == "":
        return vf.key_value_outbuf_to_dicts(ret_values, process_indent=1)
    else:
        return vf.key_value_outbuf_to_dict(ret_values, process_indent=1)


def channel_getciphers_ipmi():
    r"""
    Run 'channel getciphers ipmi' command and return the result as a list of dictionaries.

    Example robot code:
    ${ipmi_channel_ciphers}=  Channel Getciphers IPMI
    Rprint Vars  ipmi_channel_ciphers

    Example output:
    ipmi_channel_ciphers:
      [0]:
        [id]:                                         3
        [iana]:                                       N/A
        [auth_alg]:                                   hmac_sha1
        [integrity_alg]:                              hmac_sha1_96
        [confidentiality_alg]:                        aes_cbc_128
      [1]:
        [id]:                                         17
        [iana]:                                       N/A
        [auth_alg]:                                   hmac_sha256
        [integrity_alg]:                              sha256_128
        [confidentiality_alg]:                        aes_cbc_128
    """

    cmd_buf = "channel getciphers ipmi | sed -re 's/ Alg/_Alg/g'"
    stdout, stderr, rc = execute_ipmi_cmd(cmd_buf, "external", print_output=0)
    return vf.outbuf_to_report(stdout)


def get_device_id_config():
    r"""
    Get the device id config data and return as a dictionary.

    Example:

    dev_id_config =  get_device_id_config()
    print_vars(dev_id_config)

    dev_id_config:
        [manuf_id]:            7244
        [addn_dev_support]:     141
        [prod_id]:            16976
        [aux]:                    0
        [id]:                    32
        [revision]:             129
        [device_revision]:        1
    """
    stdout, stderr, rc = bsu.bmc_execute_command(
        "cat /usr/share/ipmi-providers/dev_id.json"
    )

    result = json.loads(stdout)

    # Create device revision field for the user.
    # Reference IPMI specification v2.0 "Get Device ID Command"
    # [7]   1 = device provides Device SDRs
    #       0 = device does not provide Device SDRs
    # [6:4] reserved. Return as 0.
    # [3:0] Device Revision, binary encoded.

    result["device_revision"] = result["revision"] & 0x0F

    return result


def get_chassis_status():
    r"""
    Get IPMI chassis status data and return it as a dictionary.

    The data is obtained by issuing the IPMI "chassis status" command. An
    example is shown below:

    System Power              : off
    Power Overload            : false
    Power Interlock           : inactive
    Main Power Fault          : false
    Power Control Fault       : false
    Power Restore Policy      : previous
    Last Power Event          :
    Chassis Intrusion         : inactive
    Front-Panel Lockout       : inactive
    Drive Fault               : false
    Cooling/Fan Fault         : false
    Sleep Button Disable      : not allowed
    Diag Button Disable       : not allowed
    Reset Button Disable      : not allowed
    Power Button Disable      : allowed
    Sleep Button Disabled     : false
    Diag Button Disabled      : false
    Reset Button Disabled     : false
    Power Button Disabled     : false

    For the data shown above, the following dictionary will be returned.

    chassis_status:
      [system_power]:                        off
      [power_overload]:                      false
      [power_interlock]:                     inactive
      [main_power_fault]:                    false
      [power_control_fault]:                 false
      [power_restore_policy]:                previous
      [last_power_event]:
      [chassis_intrusion]:                   inactive
      [front-panel_lockout]:                 inactive
      [drive_fault]:                         false
      [cooling/fan_fault]:                   false
      [sleep_button_disable]:                not allowed
      [diag_button_disable]:                 not allowed
      [reset_button_disable]:                not allowed
      [power_button_disable]:                allowed
      [sleep_button_disabled]:               false
      [diag_button_disabled]:                false
      [reset_button_disabled]:               false
      [power_button_disabled]:               false
    """

    status, ret_values = grk.run_key_u(
        "Run External IPMI Standard Command  chassis status"
    )
    result = vf.key_value_outbuf_to_dict(ret_values, process_indent=1)

    return result


def get_channel_info(channel_number=1):
    r"""
    Get the channel info and return as a dictionary.
    Example:

    channel_info:
      [channel_0x2_info]:
        [channel_medium_type]:                        802.3 LAN
        [channel_protocol_type]:                      IPMB-1.0
        [session_support]:                            multi-session
        [active_session_count]:                       0
        [protocol_vendor_id]:                         7154
      [volatile(active)_settings]:
        [alerting]:                                   enabled
        [per-message_auth]:                           enabled
        [user_level_auth]:                            enabled
        [access_mode]:                                always available
      [non-volatile_settings]:
        [alerting]:                                   enabled
        [per-message_auth]:                           enabled
        [user_level_auth]:                            enabled
        [access_mode]:                                always available
    """

    status, ret_values = grk.run_key_u(
        "Run IPMI Standard Command  channel info " + str(channel_number)
    )
    key_var_list = list(filter(None, ret_values.split("\n")))
    # To match the dict format, add a colon after 'Volatile(active) Settings' and 'Non-Volatile Settings'
    # respectively.
    key_var_list[6] = "Volatile(active) Settings:"
    key_var_list[11] = "Non-Volatile Settings:"
    result = vf.key_value_list_to_dict(key_var_list, process_indent=1)
    return result


def get_user_access_ipmi(channel_number=1):
    r"""
    Run 'user list [<channel number>]' command and return the result as a list of dictionaries.

    Example robot code:
    ${users_access}=  user list 1
    Rprint Vars  users_access

    Example output:
    users:
      [0]:
        [id]:                                         1
        [name]:                                       root
        [callin]:                                     false
        [link]:                                       true
        [auth]:                                       true
        [ipmi]:                                       ADMINISTRATOR
      [1]:
        [id]:                                         2
        [name]:                                       axzIDwnz
        [callin]:                                     true
        [link]:                                       false
        [auth]:                                       true
        [ipmi]:                                       ADMINISTRATOR
    """

    cmd_buf = "user list " + str(channel_number)
    stdout, stderr, rc = execute_ipmi_cmd(cmd_buf, "external", print_output=0)
    return vf.outbuf_to_report(stdout)


def get_channel_auth_capabilities(channel_number=1, privilege_level=4):
    r"""
    Get the channel authentication capabilities and return as a dictionary.

    Example:

    channel_auth_cap:
        [channel_number]:                               2
        [ipmi_v1.5__auth_types]:
        [kg_status]:                                    default (all zeroes)
        [per_message_authentication]:                   enabled
        [user_level_authentication]:                    enabled
        [non-null_user_names_exist]:                    yes
        [null_user_names_exist]:                        no
        [anonymous_login_enabled]:                      no
        [channel_supports_ipmi_v1.5]:                   no
        [channel_supports_ipmi_v2.0]:                   yes
    """

    status, ret_values = grk.run_key_u(
        "Run IPMI Standard Command  channel authcap "
        + str(channel_number)
        + " "
        + str(privilege_level)
    )
    result = vf.key_value_outbuf_to_dict(ret_values, process_indent=1)

    return result


def fetch_date(date):
    r"""
    Removes prefix 0 in a date in given date

    Example : 08/12/2021 then returns 8/12/2021
    """

    date = date.lstrip("0")
    return date


def fetch_added_sel_date(entry):
    r"""
    Split sel entry string with with | and join only the date with space

    Example : If entry given is, "a | 02/14/2020 | 01:16:58 | Sensor_type #0x17 |  | Asserted"
    Then the result will be "02/14/2020 01:16:58"
    """

    temp = entry.split(" | ")
    date = temp[1] + " " + temp[2]
    print(date)
    return date


def prefix_bytes(listx):
    r"""
    prefixes byte strings in list

    Example:
    ${listx} = ['01', '02', '03']
    ${listx}=  Prefix Bytes  ${listx}
    then,
    ${listx}= ['0x01', '0x02', '0x03']

    """

    listy = []
    for item in listx:
        item = "0x" + item
        listy.append(item)
    return listy


def modify_and_fetch_threshold(old_threshold, threshold_list):
    r"""
    Description of argument(s):

        old_threshold              List of threshold values of sensor,
        threshold_list             List of higher and lower of critical and non-critical values.
                                   i,e [ "lcr", "lnc", "unc", "ucr" ]

    Gets old threshold values from sensor and threshold levels,
    then returns the list of new threshold and the dict of threshold levels

    For example :
    1. If old_threshold list is [ 1, 2, 3, 4] then the newthreshold_list will be [ 101, 102, 103, 104 ].
       If old_threshold has 'na' the same will be appended to new list, eg: [ 101, 102, 103, 104, 'na'].

    2. The newthreshold_list will be zipped to dictionary with threshold_list levels,
       Example : threshold_dict = { 'lcr': 101, 'lnc': 102, 'unc': 103, 'ucr': 104 }

    """

    # Adding the difference of 100 as less than this value,
    # may not have greater impact as the sensor considered is a fan sensor.
    # The set threshold may round off for certain values below 100.
    n = 100
    newthreshold_list = []
    for th in old_threshold:
        th = th.strip()
        if th == "na":
            newthreshold_list.append("na")
        else:
            x = int(float(th)) + n
            newthreshold_list.append(x)
            n = n + 100
    threshold_dict = dict(zip(threshold_list, newthreshold_list))
    return newthreshold_list, threshold_dict
